/* ***************************************************************************
 **    DS1307.c
 **
 **  Project      : ClockMatrix_v0
 **  Target       : PIC18F14K50
 **  Description  : Project used to develop clock firmware.  Tested methods and
 **                 determined functionality (needed, wanted, and the possible)
 **
 **  Compiler     : HI-TECH C  Version 9.80
 **  IDE          : MPLABX v1.80
 **  Created      : 5/8/2013
 **  Branched     : 6/27/2013 -- started v2
 **
 **  R Hanlen <implod@gmail.com>
 ** ***************************************************************************/

/*****************************************************************************
 **HEADER FILES
 *****************************************************************************/
//  Global 
#include <htc.h>
#include <stdint.h>
#include <string.h>

//  Local 
#include "global.h"
//#include "numbers.h"
#include "DS1307.h"
#include "swI2C.h"

/*****************************************************************************
 **VARABLES
 *****************************************************************************/

/*****************************************************************************
 **FUNCTIONS
 *****************************************************************************/

uint8_t RTCInit(void){

    if (AckPolling(DS1307_ID)) { //check if rtc acks on i2c bus
        return(RTC_NOT_RESPONDING);
    }


    if ((RTCGetRegister(RTC_SECONDS)) & 0x80) { //check if oscillator is running
        //RTCStartClock();
        return(RTC_CLOCKHALT_BIT_SET);
    }

    return(RTC_INITIALIZED);
}

int8_t RTCStartClock(void){

    StartI2C(); // Issue start signal
    TransmitI2C(DS1307_ID); // Address
    TransmitI2C(RTC_SECONDS); // Start from address 0
    TransmitI2C(0x00);
    StopI2C();

}

void RTCStopClock(void){

    StartI2C(); // Issue start signal
    TransmitI2C(DS1307_ID); // Device
    TransmitI2C(RTC_SECONDS); // Address
    TransmitI2C(RTC_CH_BIT);
    StopI2C();

}

void RTCGetDateTime(uint8_t *dateptr){

    uint8_t i2cBuffer;
    StartI2C(); // Issue start signal
    TransmitI2C(DS1307_ID); // Device
    TransmitI2C(RTC_SECONDS); // Address
    StartI2C(); // Issue repeated start signal
    TransmitI2C(0xD1); // Device plus R/W=1
    i2cBuffer = RecieveI2C(1); // Read seconds byte
    dateptr[RTC_SECONDS] = bcd_to_dec(i2cBuffer);
    i2cBuffer = RecieveI2C(1); // Read minutes byte
    dateptr[RTC_MINUTES] = bcd_to_dec(i2cBuffer);
    i2cBuffer = RecieveI2C(1); // Read hours byte
    dateptr[RTC_HOURS] = bcd_to_dec(i2cBuffer & 0x1F);
    i2cBuffer = RecieveI2C(1); // Read day of week byte
    dateptr[RTC_DAY] = bcd_to_dec(i2cBuffer);
    i2cBuffer = RecieveI2C(1); //Read date of month
    dateptr[RTC_DATE] = bcd_to_dec(i2cBuffer);
    i2cBuffer = RecieveI2C(1); // Read month byte
    dateptr[RTC_MONTH] = bcd_to_dec(i2cBuffer);
    i2cBuffer = RecieveI2C(0); // Read last to digits of year byte
    dateptr[RTC_YEAR] = bcd_to_dec(i2cBuffer);
    StopI2C(); // Issue stop signal

}

void RTCGetTime(uint8_t *timeptr){

    uint8_t i2cBuffer;
    StartI2C(); // Issue start signal
    TransmitI2C(DS1307_ID); // Device
    TransmitI2C(RTC_SECONDS); // Address
    StartI2C(); // Issue repeated start signal
    TransmitI2C(0xD1); // Device plus R/W=1
    i2cBuffer = RecieveI2C(1); // Read seconds byte
    timeptr[0] = bcd_to_dec(i2cBuffer);
    i2cBuffer = RecieveI2C(1); // Read minutes byte
    timeptr[1] = bcd_to_dec(i2cBuffer);
    i2cBuffer = RecieveI2C(0); // Read hours byte
    timeptr[2] = bcd_to_dec(i2cBuffer & 0x1F);
    StopI2C(); // Issue stop signal

}

void RTCGetDate(uint8_t *dateptr){

    uint8_t i2cBuffer;
    StartI2C(); // Issue start signal
    TransmitI2C(DS1307_ID); // Device
    TransmitI2C(RTC_DAY); // Address
    StartI2C(); // Issue repeated start signal
    TransmitI2C(0xD1); // Device plus R/W=1
    i2cBuffer = RecieveI2C(1); // Read seconds byte
    dateptr[RTC_DAY - 3] = bcd_to_dec(i2cBuffer);
    i2cBuffer = RecieveI2C(1); // Read minutes byte
    dateptr[RTC_DATE - 3] = bcd_to_dec(i2cBuffer);
    i2cBuffer = RecieveI2C(1); // Read hours byte
    dateptr[RTC_MONTH - 3] = bcd_to_dec(i2cBuffer);
    i2cBuffer = RecieveI2C(0); // Read hours byte
    dateptr[RTC_YEAR - 3] = bcd_to_dec(i2cBuffer);
    StopI2C(); // Issue stop signal

}

uint8_t RTCGetRegister(uint8_t reg){

    uint8_t i2cBuffer;
    StartI2C(); // Issue start signal
    TransmitI2C(DS1307_ID); // Device
    TransmitI2C(reg); // Address
    StartI2C(); // Issue repeated start signal
    TransmitI2C(0xD1); // Device plus R/W=1
    i2cBuffer = RecieveI2C(0); // Read seconds byte
    StopI2C(); // Issue stop signal

    return i2cBuffer;
}


void RTCSetTime(uint8_t *timeptr){
    uint8_t i2cBuffer;

    StartI2C(); // Issue start signal
    TransmitI2C(DS1307_ID); // Device
    TransmitI2C(RTC_SECONDS); // Address
    i2cBuffer = dec_to_bcd(timeptr[RTC_SECONDS]);
    TransmitI2C(i2cBuffer); //seconds
    i2cBuffer = dec_to_bcd(timeptr[RTC_MINUTES]);
    TransmitI2C(i2cBuffer); //minutes
    i2cBuffer = dec_to_bcd(timeptr[RTC_HOURS]);
    TransmitI2C(i2cBuffer | 0x40); //hours
    i2cBuffer = dec_to_bcd(timeptr[RTC_DAY]);
    TransmitI2C(i2cBuffer); //Day
    i2cBuffer = dec_to_bcd(timeptr[RTC_DATE]);
    TransmitI2C(i2cBuffer); //Date
    i2cBuffer = dec_to_bcd(timeptr[RTC_MONTH]);
    TransmitI2C(i2cBuffer); //Month
    i2cBuffer = dec_to_bcd(timeptr[RTC_YEAR]);
    TransmitI2C(i2cBuffer); //Year
    StopI2C();

}

uint8_t RTCGetControl(void){

    return RTCGetRegister(RTC_CONTROL);
}

//uint8_t RTCGetCNTRL(void){
//
//    StartI2C(); // Issue start signal
//    TransmitI2C(DS1307_ID); // Device
//    TransmitI2C(RTC_CONTROL); //  Address
//    StartI2C(); // Issue repeated start signal
//    TransmitI2C(0xD1); // Device plus R/W=1
//    dateTime.cntrl = RecieveI2C(0);
//    StopI2C(); // Issue stop signal
//
//    return(dateTime.cntrl);
//}
//
//void RTCSetCNTRL(uint8_t value){
//
//    StartI2C(); // Issue start signal
//    TransmitI2C(DS1307_ID); // Device
//    TransmitI2C(RTC_CONTROL); //  Address
//    TransmitI2C(value);
//    StopI2C();
//}

void TimeString(char *string){

    uint8_t time[3];
    unsigned char number1, number2, number3;

    RTCGetTime(time);
    string[0] = '\0';
    // Assemble a time string
    if (time[RTC_HOURS] < 10) {
        number1 = time[RTC_HOURS];
        number2 = time[RTC_MINUTES] / 10;
        number3 = time[RTC_MINUTES] - (number2 * 10);

        string[0] = number1 + 48;
        string[1] = ':';
        string[2] = number2 + 48;
        string[3] = number3 + 48;
        string[4] = '\0';
    } else {
        number1 = time[RTC_HOURS] - 10;
        number2 = time[RTC_MINUTES] / 10;
        number3 = time[RTC_MINUTES] - (number2 * 10);

        string[0] = '1';
        string[1] = number1 + 48;
        string[2] = ':';
        string[3] = number2 + 48;
        string[4] = number3 + 48;
        string[5] = '\0';
    }

} // string length = 5

void DateString(char *string){

    uint8_t date[4];
    unsigned char number1, number2;
    int length;

    RTCGetDate(date);
    // Blank the string
    string[0] = '\0';

    switch (date[0]) {
        case 1: strcat(string, "Monday ");
            break;
        case 2: strcat(string, "Tuesday ");
            break;
        case 3: strcat(string, "Wednesday ");
            break;
        case 4: strcat(string, "Thursday ");
            break;
        case 5: strcat(string, "Friday ");
            break;
        case 6: strcat(string, "Saturday ");
            break;
        case 7: strcat(string, "Sunday ");
            break;
    }

    strcat(string, "the ");

    if (date[1] < 10) number1 = 0;
    else number1 = date[1] / 10;

    number2 = date[1] - (number1 * 10);

    if (number1 > 0) {
        length = strlen(string);
        string[length] = number1 + 48;
        string[length + 1] = '\0';
    }

    length = strlen(string);
    string[length] = number2 + 48;
    string[length + 1] = '\0';

    if (number1 == 1) {
        strcat(string, "th of ");
    } else {
        if (number2 == 1) strcat(string, "st of ");
        else if (number2 == 2) strcat(string, "nd of ");
        else if (number2 == 3) strcat(string, "rd of ");
        else strcat(string, "th of ");
    }

    switch (date[2]) {
        case 1: strcat(string, "January ");
            break;
        case 2: strcat(string, "Febuary ");
            break;
        case 3: strcat(string, "March ");
            break;
        case 4: strcat(string, "April ");
            break;
        case 5: strcat(string, "May ");
            break;
        case 6: strcat(string, "June ");
            break;
        case 7: strcat(string, "July ");
            break;
        case 8: strcat(string, "August ");
            break;
        case 9: strcat(string, "September ");
            break;
        case 10: strcat(string, "October ");
            break;
        case 11: strcat(string, "November ");
            break;
        case 12: strcat(string, "December ");
            break;
    }

    strcat(string, "20");

    if (date[3] < 10) number1 = 0;
    else number1 = date[3] / 10;

    number2 = date[3] - (number1 * 10);

    length = strlen(string);
    string[length] = number1 + 48;
    string[length + 1] = number2 + 48;
    string[length + 2] = '\0';
}  // string length <= 36

uint8_t bcd_to_dec(uint8_t bcd){
    return(bcd & 0x0f) + ((bcd >> 4) * 10);
}

uint8_t dec_to_bcd(uint8_t dec){
    return(((dec / 10) << 4)+ (dec % 10));
}